﻿using System;
using System.Collections.Generic;

namespace UniRx.Operators
{
	// Token: 0x020002BF RID: 703
	internal class MergeObservable<T> : OperatorObservableBase<T>
	{
		// Token: 0x06000F35 RID: 3893 RVA: 0x00046C30 File Offset: 0x00045030
		public MergeObservable(IObservable<IObservable<T>> sources, bool isRequiredSubscribeOnCurrentThread) : base(isRequiredSubscribeOnCurrentThread)
		{
			this.sources = sources;
		}

		// Token: 0x06000F36 RID: 3894 RVA: 0x00046C40 File Offset: 0x00045040
		public MergeObservable(IObservable<IObservable<T>> sources, int maxConcurrent, bool isRequiredSubscribeOnCurrentThread) : base(isRequiredSubscribeOnCurrentThread)
		{
			this.sources = sources;
			this.maxConcurrent = maxConcurrent;
		}

		// Token: 0x06000F37 RID: 3895 RVA: 0x00046C57 File Offset: 0x00045057
		protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
		{
			if (this.maxConcurrent > 0)
			{
				return new MergeObservable<T>.MergeConcurrentObserver(this, observer, cancel).Run();
			}
			return new MergeObservable<T>.MergeOuterObserver(this, observer, cancel).Run();
		}

		// Token: 0x040008DA RID: 2266
		private readonly IObservable<IObservable<T>> sources;

		// Token: 0x040008DB RID: 2267
		private readonly int maxConcurrent;

		// Token: 0x020002C0 RID: 704
		private class MergeOuterObserver : OperatorObserverBase<IObservable<T>, T>
		{
			// Token: 0x06000F38 RID: 3896 RVA: 0x00046C80 File Offset: 0x00045080
			public MergeOuterObserver(MergeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000F39 RID: 3897 RVA: 0x00046C9C File Offset: 0x0004509C
			public IDisposable Run()
			{
				this.collectionDisposable = new CompositeDisposable();
				this.sourceDisposable = new SingleAssignmentDisposable();
				this.collectionDisposable.Add(this.sourceDisposable);
				this.sourceDisposable.Disposable = this.parent.sources.Subscribe(this);
				return this.collectionDisposable;
			}

			// Token: 0x06000F3A RID: 3898 RVA: 0x00046CF4 File Offset: 0x000450F4
			public override void OnNext(IObservable<T> value)
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				this.collectionDisposable.Add(singleAssignmentDisposable);
				MergeObservable<T>.MergeOuterObserver.Merge observer = new MergeObservable<T>.MergeOuterObserver.Merge(this, singleAssignmentDisposable);
				singleAssignmentDisposable.Disposable = value.Subscribe(observer);
			}

			// Token: 0x06000F3B RID: 3899 RVA: 0x00046D28 File Offset: 0x00045128
			public override void OnError(Exception error)
			{
				object obj = this.gate;
				lock (obj)
				{
					try
					{
						this.observer.OnError(error);
					}
					finally
					{
						base.Dispose();
					}
				}
			}

			// Token: 0x06000F3C RID: 3900 RVA: 0x00046D84 File Offset: 0x00045184
			public override void OnCompleted()
			{
				this.isStopped = true;
				if (this.collectionDisposable.Count == 1)
				{
					object obj = this.gate;
					lock (obj)
					{
						try
						{
							this.observer.OnCompleted();
						}
						finally
						{
							base.Dispose();
						}
					}
				}
				else
				{
					this.sourceDisposable.Dispose();
				}
			}

			// Token: 0x040008DC RID: 2268
			private readonly MergeObservable<T> parent;

			// Token: 0x040008DD RID: 2269
			private CompositeDisposable collectionDisposable;

			// Token: 0x040008DE RID: 2270
			private SingleAssignmentDisposable sourceDisposable;

			// Token: 0x040008DF RID: 2271
			private object gate = new object();

			// Token: 0x040008E0 RID: 2272
			private bool isStopped;

			// Token: 0x020002C1 RID: 705
			private class Merge : OperatorObserverBase<T, T>
			{
				// Token: 0x06000F3D RID: 3901 RVA: 0x00046E08 File Offset: 0x00045208
				public Merge(MergeObservable<T>.MergeOuterObserver parent, IDisposable cancel) : base(parent.observer, cancel)
				{
					this.parent = parent;
					this.cancel = cancel;
				}

				// Token: 0x06000F3E RID: 3902 RVA: 0x00046E28 File Offset: 0x00045228
				public override void OnNext(T value)
				{
					object gate = this.parent.gate;
					lock (gate)
					{
						this.observer.OnNext(value);
					}
				}

				// Token: 0x06000F3F RID: 3903 RVA: 0x00046E74 File Offset: 0x00045274
				public override void OnError(Exception error)
				{
					object gate = this.parent.gate;
					lock (gate)
					{
						try
						{
							this.observer.OnError(error);
						}
						finally
						{
							base.Dispose();
						}
					}
				}

				// Token: 0x06000F40 RID: 3904 RVA: 0x00046ED8 File Offset: 0x000452D8
				public override void OnCompleted()
				{
					this.parent.collectionDisposable.Remove(this.cancel);
					if (this.parent.isStopped && this.parent.collectionDisposable.Count == 1)
					{
						object gate = this.parent.gate;
						lock (gate)
						{
							try
							{
								this.observer.OnCompleted();
							}
							finally
							{
								base.Dispose();
							}
						}
					}
				}

				// Token: 0x040008E1 RID: 2273
				private readonly MergeObservable<T>.MergeOuterObserver parent;

				// Token: 0x040008E2 RID: 2274
				private readonly IDisposable cancel;
			}
		}

		// Token: 0x020002C2 RID: 706
		private class MergeConcurrentObserver : OperatorObserverBase<IObservable<T>, T>
		{
			// Token: 0x06000F41 RID: 3905 RVA: 0x00046F78 File Offset: 0x00045378
			public MergeConcurrentObserver(MergeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000F42 RID: 3906 RVA: 0x00046F94 File Offset: 0x00045394
			public IDisposable Run()
			{
				this.q = new Queue<IObservable<T>>();
				this.activeCount = 0;
				this.collectionDisposable = new CompositeDisposable();
				this.sourceDisposable = new SingleAssignmentDisposable();
				this.collectionDisposable.Add(this.sourceDisposable);
				this.sourceDisposable.Disposable = this.parent.sources.Subscribe(this);
				return this.collectionDisposable;
			}

			// Token: 0x06000F43 RID: 3907 RVA: 0x00046FFC File Offset: 0x000453FC
			public override void OnNext(IObservable<T> value)
			{
				object obj = this.gate;
				lock (obj)
				{
					if (this.activeCount < this.parent.maxConcurrent)
					{
						this.activeCount++;
						this.Subscribe(value);
					}
					else
					{
						this.q.Enqueue(value);
					}
				}
			}

			// Token: 0x06000F44 RID: 3908 RVA: 0x00047070 File Offset: 0x00045470
			public override void OnError(Exception error)
			{
				object obj = this.gate;
				lock (obj)
				{
					try
					{
						this.observer.OnError(error);
					}
					finally
					{
						base.Dispose();
					}
				}
			}

			// Token: 0x06000F45 RID: 3909 RVA: 0x000470CC File Offset: 0x000454CC
			public override void OnCompleted()
			{
				object obj = this.gate;
				lock (obj)
				{
					this.isStopped = true;
					if (this.activeCount == 0)
					{
						try
						{
							this.observer.OnCompleted();
						}
						finally
						{
							base.Dispose();
						}
					}
					else
					{
						this.sourceDisposable.Dispose();
					}
				}
			}

			// Token: 0x06000F46 RID: 3910 RVA: 0x0004714C File Offset: 0x0004554C
			private void Subscribe(IObservable<T> innerSource)
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				this.collectionDisposable.Add(singleAssignmentDisposable);
				MergeObservable<T>.MergeConcurrentObserver.Merge observer = new MergeObservable<T>.MergeConcurrentObserver.Merge(this, singleAssignmentDisposable);
				singleAssignmentDisposable.Disposable = innerSource.Subscribe(observer);
			}

			// Token: 0x040008E3 RID: 2275
			private readonly MergeObservable<T> parent;

			// Token: 0x040008E4 RID: 2276
			private CompositeDisposable collectionDisposable;

			// Token: 0x040008E5 RID: 2277
			private SingleAssignmentDisposable sourceDisposable;

			// Token: 0x040008E6 RID: 2278
			private object gate = new object();

			// Token: 0x040008E7 RID: 2279
			private bool isStopped;

			// Token: 0x040008E8 RID: 2280
			private Queue<IObservable<T>> q;

			// Token: 0x040008E9 RID: 2281
			private int activeCount;

			// Token: 0x020002C3 RID: 707
			private class Merge : OperatorObserverBase<T, T>
			{
				// Token: 0x06000F47 RID: 3911 RVA: 0x00047180 File Offset: 0x00045580
				public Merge(MergeObservable<T>.MergeConcurrentObserver parent, IDisposable cancel) : base(parent.observer, cancel)
				{
					this.parent = parent;
					this.cancel = cancel;
				}

				// Token: 0x06000F48 RID: 3912 RVA: 0x000471A0 File Offset: 0x000455A0
				public override void OnNext(T value)
				{
					object gate = this.parent.gate;
					lock (gate)
					{
						this.observer.OnNext(value);
					}
				}

				// Token: 0x06000F49 RID: 3913 RVA: 0x000471EC File Offset: 0x000455EC
				public override void OnError(Exception error)
				{
					object gate = this.parent.gate;
					lock (gate)
					{
						try
						{
							this.observer.OnError(error);
						}
						finally
						{
							base.Dispose();
						}
					}
				}

				// Token: 0x06000F4A RID: 3914 RVA: 0x00047250 File Offset: 0x00045650
				public override void OnCompleted()
				{
					this.parent.collectionDisposable.Remove(this.cancel);
					object gate = this.parent.gate;
					lock (gate)
					{
						if (this.parent.q.Count > 0)
						{
							IObservable<T> innerSource = this.parent.q.Dequeue();
							this.parent.Subscribe(innerSource);
						}
						else
						{
							this.parent.activeCount--;
							if (this.parent.isStopped && this.parent.activeCount == 0)
							{
								try
								{
									this.observer.OnCompleted();
								}
								finally
								{
									base.Dispose();
								}
							}
						}
					}
				}

				// Token: 0x040008EA RID: 2282
				private readonly MergeObservable<T>.MergeConcurrentObserver parent;

				// Token: 0x040008EB RID: 2283
				private readonly IDisposable cancel;
			}
		}
	}
}
